<template>
  <div class="dialog-container">
    <div class="dialog-content">
      <el-upload
        ref="upload"
        multiple
        :show-file-list="false"
        :file-list="fileList"
        :limit="limit"
        :accept="accept"
        action=""
        :before-upload="handleBeforeUpload"
        :on-success="handleSuccess"
        :on-progress="handleProgress"
        :http-request="handleUpload"
        list-type="picture-card"
        :on-exceed="handleOnExceed"
      >
        <i class="el-icon-plus"></i>
      </el-upload>
      <draggable v-model="dragList" chosenClass="chosen" forceFallback="true" animation="1000" filter=".undraggable" @start="handleDragStart" @end="handleDragEnd" class="drag-box">
        <div class="img-box" v-for="(item, index) in dragList" :key="index">
          <img :src="item.onlineUrl || item.url" class="img" />
          <div v-if="item.status === 'success'" class="icon-success">
            <i class="el-icon-check"></i>
          </div>
          <div v-if="item.status === 'uploading'" class="icon-box icon-loading">
            <i class="el-icon-loading"></i>
            <p class="text">上传中...</p>
          </div>
          <div v-if="item.status === 'success'" class="icon-box icon-delete">
            <img :src="item.onlineUrl || item.url" class="img hidden" v-viewer="viewerOptions" />
            <div class="line">
              <i class="el-icon-scissors undraggable" @click.stop.prevent="handleCropper(index)"></i>
              <i class="el-icon-delete undraggable" @click.stop.prevent="handleDelete(index)"></i>
            </div>
          </div>
          <div v-if="item.status === 'error'" class="icon-box icon-error">
            <div class="line">
              <i class="el-icon-refresh-right undraggable" @click.stop.prevent="handleRetry(index)"></i>
              <i class="el-icon-delete undraggable" @click.stop.prevent="handleDelete(index)"></i>
            </div>
            <p class="text">重试</p>
          </div>
        </div>
      </draggable>
    </div>
    <div class="text-tip">支持上传jpg,png格式图片,最大不超过10MB,可左右拖动交换图片位置</div>

    <!--  图片剪裁-->
    <el-dialog title="图片剪裁" :close-on-click-modal="false" :append-to-body="true" :lock-scroll="true" :visible.sync="showCropper" width="60%" @close="handleCropperCancel">
      <ImageCropper @close="handleCropperCancel" @submit="handleCropperDone" v-if="showCropper" :url="cropperUrl" :urlType="urlType" :autoCropWidth="cropSize.width" :autoCropHeight="cropSize.height"></ImageCropper>
    </el-dialog>
  </div>
</template>

<script>
import { getToken } from '@/utils/auth'
import draggable from 'vuedraggable'
import ImageCropper from './ImageCropper'
import { upyunUpload } from '@/utils/upyun'

export default {
  name: 'ImageDraggable',
  components: { draggable, ImageCropper },
  props: {
    watermark: {
      type: Boolean,
      default: true,
    },
    infoType: {
      type: String,
      default: 'asset',
    },
  },
  data() {
    return {
      showCropper: false,
      cropSize: {
        width: 400,
        height: 400,
      },
      cropperUrl: '',
      urlType: 'url',
      limit: 10,
      accept: 'image/jpeg,image/jpg,image/png',
      fileList: [],
      dragList: [],
      viewerOptions: {
        button: true,
        navbar: false,
        title: true,
        toolbar: false,
        tooltip: false,
        movable: false,
        zoomable: true,
        rotatable: false,
        scalable: true,
        transition: false,
        fullscreen: false,
        keyboard: true,
      },
      cropperIndex: 0,
      cropperFile: '',
      selectedFileList: [],
      timer: null,
    }
  },
  watch: {},
  mounted() {},
  methods: {
    getToken() {
      return getToken()
    },
    setValue(value) {
      if (value) {
        let list = value.split('|')
        this.fileList = this.dragList = list
          .filter((item) => item !== '')
          .map((item) => {
            return {
              name: '',
              onlineUrl: item,
              status: 'success',
              uid: '',
              url: item,
            }
          })
      }
    },
    // 上传前
    handleBeforeUpload(file) {
      let isRightSize = file.size / 1024 / 1024 < 10
      if (!isRightSize) {
        this.$message.error('文件大小超过 10MB')
      }
      return isRightSize
    },
    // 上传中
    handleProgress(event, file, fileList) {},

    // 上传成功
    handleSuccess(response, file, fileList) {},
    // 删除图片
    handleDelete(index) {
      this.dragList.splice(index, 1)
      this.$emit('change', this.dragList)
    },
    // 剪裁图片
    handleCropper(index) {
      this.cropperIndex = index
      this.cropperFile = this.dragList[index]
      const that = this
      if (this.cropperFile.raw) {
        var reader = new FileReader()
        reader.readAsDataURL(this.cropperFile.raw)
        reader.onloadend = function (e) {
          that.cropperUrl = e.target.result
          this.urlType = 'base64'
          setTimeout(() => {
            that.showCropper = true
          }, 500)
        }
      } else {
        this.cropperUrl = this.dragList[index].url
        this.urlType = 'url'
        this.showCropper = true
      }
    },
    //开始拖拽事件
    handleDragStart() {},
    //拖拽结束事件
    handleDragEnd() {
      this.$emit('change', this.dragList)
    },
    // 重新上传
    handleRetry(index) {
      this.cropperIndex = index
      this.dragList[index].status = 'uploading'
      this.upload(this.dragList[index].raw)
    },
    handleCropperCancel() {
      this.showCropper = false
      if (this.cropperIndex === this.dragList.length) {
        this.selectedFileList = []
      }
    },
    // 剪裁完成
    handleCropperDone({ url, urlType }) {
      this.showCropper = false
      if (this.cropperIndex === this.dragList.length) {
        this.dragList.push({
          name: this.cropperFile.name,
          percentage: 0,
          raw: this.cropperFile,
          size: this.cropperFile.size,
          status: 'uploading',
          uid: this.cropperFile.uid,
          url: this.cropperFile.url,
        })
      }
      if (this.isBase64(url)) {
        const name = this.cropperFile.name || 'image'
        const file = this.base64ToFile(url, name)
        this.dragList[this.cropperIndex].raw = file
        this.dragList[this.cropperIndex].size = file.size
        file.uid = this.dragList[this.cropperIndex].uid
        this.upload(file, this.cropperIndex)
      }
      this.urlType = urlType
    },
    isBase64(str) {
      return str.includes('base64')
    },
    upload(file, index) {
      if (index === undefined) {
        index = this.dragList.findIndex((item) => item.uid === file.uid)
      }
      upyunUpload({ file, watermark: this.watermark, info_type: this.infoType })
        .then((res) => {
          if (res) {
            this.$set(this.dragList[index], 'onlineUrl', res)
            this.$set(this.dragList[index], 'status', 'success')
            this.$emit('change', this.dragList)
            this.selectedFileList = this.selectedFileList.filter((item) => item.file.uid !== file.uid)
          }
        })
        .catch(() => {
          this.$set(this.dragList[index], 'status', 'error')
          this.selectedFileList = this.selectedFileList.filter((item) => item.file.uid !== file.uid)
        })
    },
    // 自定义上传
    handleUpload(param) {
      this.selectedFileList.push(param)
      if (this.timer) {
        clearTimeout(this.timer)
        this.timer = null
      }
      this.timer = setTimeout(() => {
        if (this.selectedFileList.length === 1) {
          this.cropperFile = param.file
          const that = this
          var reader = new FileReader()
          reader.readAsDataURL(param.file)
          reader.onloadend = function (e) {
            that.cropperIndex = that.dragList.length
            that.cropperUrl = e.target.result
            that.urlType = 'base64'
            setTimeout(() => {
              that.showCropper = true
            }, 500)
          }
        } else {
          this.selectedFileList.forEach((item) => {
            this.dragList.push({
              name: item.file.name,
              percentage: 0,
              raw: item.file,
              size: item.file.size,
              status: 'uploading',
              uid: item.file.uid,
              url: item.file.url,
            })
            this.upload(item.file)
          })
        }
      }, 500)
    },
    base64ToFile(base64Data, fileName) {
      //将base64转换为blob
      var arr = base64Data.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n)

      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      const blob = new Blob([u8arr], { type: mime })
      return new File([blob], fileName, { type: blob.type })
    },
    // 重置
    reset() {
      this.showCropper = false
      this.cropperUrl = ''
      this.fileList = this.dragList = []
      this.cropperIndex = 0
      this.cropperFile = ''
    },
    handleOnExceed() {
      this.$message({
        type: 'error',
        message: '最多上传10张图片',
      })
    },
  },
}
</script>

<style scoped lang="scss">
.unDrag {
  margin: 0 8px 8px 0;
}
/*选中样式*/
.chosen {
  border: solid 2px #3089dc !important;
}

.img-box {
  width: 80px;
  height: 80px;
  overflow: hidden;
  background-color: #fff;
  border: 1px solid #c0ccda;
  border-radius: 6px;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  margin: 0 8px 8px 0;
  position: relative;
  font-size: 12px;
  color: #ffffff;
  .img {
    width: 100%;
    height: 100%;
    user-select: none;
    &.hidden {
      position: absolute;
      left: 0;
      top: 0;
      opacity: 0.1;
    }
  }
  .icon-success {
    position: absolute;
    right: -15px;
    top: -6px;
    width: 40px;
    height: 24px;
    background: #13ce66;
    text-align: center;
    -webkit-transform: rotate(45deg);
    transform: rotate(45deg);
    -webkit-box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2);
    box-shadow: 0 0 1pc 1px rgba(0, 0, 0, 0.2);
    i {
      margin-top: 11px;
      -webkit-transform: rotate(-45deg);
      transform: rotate(-45deg);
    }
  }
  .icon-box {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background: rgba(0, 0, 0, 0.5);
    font-size: 20px;
    .text {
      font-size: 12px;
    }
    .line {
    }
  }
  .icon-loading i {
    font-size: 20px;
  }
  .icon-delete {
    display: none;
  }
  .icon-delete,
  .icon-error {
    i {
      cursor: pointer;
    }
    .line {
      padding: 10px 10px 0;
      width: 100%;
      margin-bottom: 6px;
      display: flex;
      justify-content: space-around;
      align-items: center;
      position: relative;
      z-index: 10;
    }
  }
  &:hover {
    .icon-delete {
      display: flex;
    }
  }
}
.dialog-content {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
}
.drag-box {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  flex-wrap: wrap;
}
::v-deep .el-upload {
  margin: 0 8px 8px 0;
  width: 80px;
  height: 80px;
}
::v-deep .el-upload--picture-card {
  line-height: 90px;
}
</style>
